import 'package:analyzer/dart/element/element.dart' as ele;
import 'package:source_gen/source_gen.dart';
import 'package:build/build.dart';
import 'package:xanno/src/anno/utils/log.dart';
import 'package:xanno/src/anno/utils/pars_params.dart';
import 'dart:io';
import 'color.dart';
import 'tpl/tpl.dart' as tpl;

enum RegType {
  color,
  colors,
  colors_num,
  color_fromARGB,
  color_fromRGBO,
}

class ColorGenerator extends GeneratorForAnnotation<GColor> {
  final separator = Platform.pathSeparator;
  var colorMap = {};

  //记录之前生成的配置
  Map<String, String> updateColorMap = {};

  //记录有效
  var effectiveMap = {};
  List colorRegs = [
    {"reg": r"Color\((\s+)?0x[a-zA-Z0-9]+(\s+)?\)", "type": RegType.color},
    //优先级高于RegType.colors，不然会将Colors.red[200]匹配，提前修改为colors_red[200]
    {"reg": r"Colors\.\w+\[(\s+)?\d+(\s+)?\](!)?", "type": RegType.colors_num},
    {"reg": r"Colors\.\w+", "type": RegType.colors},
    {
      "reg":
          r"Color.fromARGB\((\s+)?\d+(\s+)?,(\s+)?\d+(\s+)?,(\s+)?\d+(\s+)?,(\s+)?\d+(\s+)?\)",
      "type": RegType.color_fromARGB
    },
    {
      "reg":
          r"Color.fromRGBO\((\s+)?\d+(\s+)?,(\s+)?\d+(\s+)?,(\s+)?\d+(\s+)?,(\s+)?\d+(\s+)?\)",
      "type": RegType.color_fromRGBO
    },
  ];
  List ignores = [
    '.color.dart',
  ];
  List ignoreColor = [
    'Colors.primaries',
    'Colors.accents',
  ];

  void readFile(path) {
    try {
      File file = File(path);
      bool exists = file.existsSync();
      if (exists) {
        //文件存在
        var lines = file.readAsLinesSync();
        lines.forEach((line) {
          RegExp(r"static Color.*").allMatches(line).forEach((v) {
            String cStr = v.group(0)!;
            var arr = cStr.substring(0, cStr.length - 1).split(' = ');
            var key = arr.first.split(' ').last;
            var value = arr.last;
            updateColorMap[key] = value;
          });
        });
      }
    } catch (e) {
      logPrint('读取文件失败! $path $e', level: Level.error);
    }
  }

  void updateFiles(String root, {package, required String importStr}) {
    try {
      var directory = Directory(root);
      List<FileSystemEntity> files = directory.listSync();
      files.forEach((f) async {
        var bool = FileSystemEntity.isFileSync(f.path);
        if (!bool) {
          updateFiles(f.path, package: package, importStr: importStr);
        } else {
          ///之后可以通过文件hash 来判断文件是否被变化，提高效率
          var ignoreItem;
          try {
            ignoreItem =
                ignores.firstWhere((element) => f.path.endsWith(element));
          } catch (e) {}
          if (ignoreItem == null && f.path.endsWith('.dart')) {
            await updateColorLine(f.path,
                package: package, importStr: importStr);
          }
        }
      });
    } catch (e) {
      logPrint("目录不存在！$root", level: Level.error);
    }
  }

  updateColorLine(path, {package, required String importStr}) async {
    try {
      File file = File(path);
      var lines = file.readAsLinesSync();
      var newLines = [];
      //文件是否被匹配到最少一次
      bool fileFlag = false;
      //import
      bool importFlag = true;
      lines.forEach((line) {
        if (line.trim() == importStr) {
          importFlag = false;
        }
        //查看原有生成的是否还存在
        updateColorMap.forEach((key, value) {
          if (line.contains(key)) {
            //记录有效
            effectiveMap[key] = value;
          }
        });

        var newLine = line;
        bool preFlag = false;
        bool childFlag = false;
        colorRegs.forEach((regObj) {
          var reg = regObj['reg'];
          var type = regObj['type'];
          RegExp(reg).allMatches(line).forEach((v) {
            //起码匹配过一次
            preFlag = true;
            childFlag = true;
            fileFlag = true;
            String colorValue = v.group(0)!;
            if (!ignoreColor.contains(colorValue)) {
              String? colorKey = getColorKey(type, colorValue);
              if (colorKey != null) {
                colorMap[colorKey] = colorValue;
                newLine =
                    newLine.replaceAll(colorValue, 'ColorConstant.$colorKey');
              }
            }
          });
        });
        if (childFlag) {
          // colorRegs匹配到才添加
          newLines.add(newLine);
        }
        if (!preFlag) {
          //一次没匹配过
          newLines.add(newLine);
        }
      });

      //将有效配置，存入colorMap
      effectiveMap.forEach((key, value) {
        colorMap[key] = value;
      });

      if (fileFlag && importFlag) {
        //最少匹配到一个， 导入import
        newLines.insert(0, importStr);
      }

      var sb = StringBuffer();
      newLines.forEach((line) {
        sb.writeln(line);
      });

      ///写入文件
      await file.writeAsString(sb.toString());
    } catch (e) {
      logPrint('读取文件失败! $path $e', level: Level.error);
    }
  }

  String? getColorKey(type, String colorValue) {
    String? colorKey;
    switch (type) {
      case RegType.color:
        colorKey = 'color_' + colorValue.substring(6, colorValue.length - 1);
        break;
      case RegType.color_fromARGB:
        colorKey = 'color_argb_' +
            colorValue
                .substring(15, colorValue.length - 1)
                .replaceAll(' ', '')
                .split(',')
                .join('_');
        break;
      case RegType.color_fromRGBO:
        colorKey = 'color_rgbo_' +
            colorValue
                .substring(15, colorValue.length - 1)
                .replaceAll(' ', '')
                .split(',')
                .join('_');
        break;
      case RegType.colors:
        colorKey = 'colors_' + colorValue.split('.').last;
        break;
      case RegType.colors_num:
        colorKey = 'colors_' +
            colorValue
                .split('.')
                .last
                .replaceAll('[', '')
                .replaceAll(']', '')
                .replaceAll('!', '');
        break;
      default:
        colorKey = null;
        break;
    }
    return colorKey;
  }

  String buildConstant(Map map) {
    var sb = StringBuffer();
    map.forEach((key, value) {
      if (value is String) {
        value = value.replaceAllMapped(
            RegExp(r"Colors\.\w+\[(\s+)?\d+(\s+)?\](!)?"),
            (match) => match.group(0)!.replaceAll(RegExp(r"!+"), '') + '!');
        sb.writeln("  // ignore: non_constant_identifier_names");
        sb.writeln("  static Color $key = $value;");
      }
    });
    return sb.toString();
  }

  @override
  generateForAnnotatedElement(
      ele.Element element, ConstantReader annotation, BuildStep buildStep) {
    // logPrint('start color', level: Level.info);
    final map = ParsParams.pars(
        annotation, {'enable': false, 'dir': '', 'name': '', 'suffix': ''});
    bool enable = map['enable'];
    String dir = map['dir'];
    String name = map['name'];
    String suffix = map['suffix'];
    if (!enable) return null;

    String fileDir = dir.split('/').join(separator);
    String fileName = '$separator$name';
    String impDir = dir.split('/').skip(1).join('/');
    String importStr =
        "import 'package:${buildStep.inputId.package}/$impDir/$name$suffix';";

    //读取已经生成的文件配置
    readFile('${Directory.current.path}$separator$fileDir$fileName$suffix');
    //查找color并修改文件
    updateFiles(
      '${Directory.current.path}${separator}lib',
      package: buildStep.inputId.package,
      importStr: importStr,
    );
    //生成ColorConstant class
    File('${Directory.current.path}$separator$fileDir$fileName$suffix')
      ..createSync(recursive: true)
      ..writeAsStringSync(
          tpl.clazzTpl(
            buildCode: buildConstant(colorMap),
            package: buildStep.inputId.package,
          ),
          flush: true);
    return null;
  }
}

Builder colorBuilder(BuilderOptions options) =>
    LibraryBuilder(ColorGenerator(), generatedExtension: ".color.dart");
